﻿/****************************** Module Header ******************************\
 * Module Name:  FormBinder.cs
 * Module Version:  1.0.0 (2012-2-23)
 * Copyright (c) AnyEB.Com (14507247@qq.com)
 * 
 * This class is used to build sql statement by entity. It supplies public 
 * method of create insert,update,delete,select,and uion query many table.
 * 
 * This source is subject to the GPL License.
 * See http://www.gnu.org/licenses/gpl.html.
 * All other rights reserved.
 * 
 * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
 * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
 * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Reflection;

namespace UCF.Core.Web
{
    using CustomControls;
    /// <summary>
    /// 表单自动装配器
    /// </summary>
    public class FormBinder
    {
        public Dictionary<string, string> MessageSet = new Dictionary<string, string>();
        private IList<TreeListComboBox> lstTreeListComboBox = new List<TreeListComboBox>();
        private IList<CNRegionComboBox> lstCnRegionComboBox = new List<CNRegionComboBox>();
        /// <summary>
        /// TreeListComboBox控件列表
        /// </summary>
        private IList<string> treeListComboBoxList = new List<string>();

        /// <summary>
        /// CNRegionComboBox控件列表
        /// </summary>
        private IList<string> cnRegionComboBoxList = new List<string>();
        /// <summary>
        /// 添加消息
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="title"></param>
        public void AddMessage(string msg, string title = "")
        {
            if (title.Length == 0) title = (this.MessageSet.Count + 1).ToString();
            this.MessageSet[title] = msg;
        }

        /// <summary>
        /// 检测表单参数类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <param name="errTip"></param>
        /// <param name="minLength"></param>
        /// <param name="maxLength"></param>
        /// <returns></returns>
        public bool CheckFormParameter<T>(string value, string errTip, int minLength = 1, int maxLength = 0)
        {
            return value.IsValidParameter<T>(ref this.MessageSet, errTip, minLength, maxLength);
        }

        /// <summary>
        /// 检测是否有消息
        /// </summary>
        /// <returns></returns>
        public bool CheckMessage(ref string msg)
        {
            if (this.MessageSet.Count == 0) return true;
            msg=this.MessageSet.Values.ToString(Environment.NewLine);
            return false;
        }

        /// <summary>
        /// 添加TreeListComboBox控件名称
        /// </summary>
        /// <param name="controlIDs"></param>
        public void AddTreeListComboBoxes(params string[] controlIDs)
        {
            foreach (string s in controlIDs)
            {
                this.treeListComboBoxList.Add(s);
            }
        }

        /// <summary>
        /// 添加CNRegionComboBox控件名称
        /// </summary>
        /// <param name="controlIDs"></param>
        public void AddCNRegionComboBoxes(params string[] controlIDs)
        {
            foreach (string s in controlIDs)
            {
                this.cnRegionComboBoxList.Add(s);
            }
        }

        /// <summary>
        /// 绑定数据实体到表单控件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        /// <param name="controlPrefix"></param>
        /// <param name="controls">母版页容器对象</param>
        public void BindForm<T>(ref T entity, string controlPrefix, IList<Control> controls)
        {
            if (entity == null) return;
            Control c;
            Type t = typeof(T);
            object v;
            foreach (string s in this.treeListComboBoxList)
            {
                c = controls.SingleOrDefault(a=>a.ID==s);
                if (c == null) continue;
                // 自定义下拉控件
                if (c.GetType() == typeof(TreeListComboBox))
                {
                    v = this.GetEntityValue(ref entity, s.Substring(controlPrefix.Length) + "ID");
                    if (v == null) continue;
                    ((TreeListComboBox)c).Value = v.ToString();
                    continue;
                }
                // 自定义下拉控件
                if (c.GetType() == typeof(JqCombo))
                {
                    v = this.GetEntityValue(ref entity, s.Substring(controlPrefix.Length) + "ID");
                    if (v == null) continue;
                    ((JqCombo)c).Value = v.ToString();
                    continue;
                }
                // 普通下拉控件
                if (c.GetType() == typeof(DropDownList))
                {
                    v = this.GetEntityValue(ref entity, s.Substring(controlPrefix.Length) + "ID");
                    if (v == null) continue;
                    ((DropDownList)c).SelectedValue = v.ToString();
                    continue;
                }
            }
            foreach (string s in this.cnRegionComboBoxList)
            {
                c = controls.SingleOrDefault(a => a.ID == s);
                if (c == null) continue;
                // 中国省市区控件
                if (c.GetType() == typeof(CNRegionComboBox))
                {
                    foreach (string cnregion in new string[] { "Province", "City", "Area" })
                    {
                        v = this.GetEntityValue(ref entity, cnregion);
                        if (v == null) continue;
                        switch (cnregion)
                        {
                            case "Province":
                                ((CNRegionComboBox)c).ProvinceValue = v.ToString();
                                break;
                            case "City":
                                ((CNRegionComboBox)c).CityValue = v.ToString();
                                break;
                            case "Area":
                                ((CNRegionComboBox)c).AreaValue = v.ToString();
                                break;
                        }
                    }
                    continue;
                }
            }
            foreach (PropertyInfo pi in t.GetProperties())
            {
                c = controls.SingleOrDefault(a => a.ID == controlPrefix + pi.Name);
                if (c == null) continue;
                v = pi.GetValue(entity, null);
                if (v == null) continue;
                if (c.GetType() == typeof(TextBox))
                {
                    ((TextBox)c).Text = (pi.PropertyType == typeof(decimal?)) ? ((decimal)v).ToString("0.00") : v.ToString();
                    continue;
                }
                if (c.GetType() == typeof(Label))
                {
                    ((Label)c).Text = v.ToString();
                    continue;
                }
                if (c.GetType() == typeof(HiddenField))
                {
                    ((HiddenField)c).Value = v.ToString();
                    continue;
                }
                if (c.GetType() == typeof(RadioButtonList))
                {
                    if (pi.PropertyType == typeof(bool?) || pi.PropertyType == typeof(bool))
                    {
                        ((RadioButtonList)c).SelectedValue = v.ToString().ToBoolean().ToInt().ToString();
                        continue;
                    }
                    ((RadioButtonList)c).SelectedValue = v.ToString();
                    continue;
                }
                if (c.GetType() == typeof(CheckBox))
                {
                    ((CheckBox)c).Checked = v.ToString().ToBoolean();
                    continue;
                }
                // 自定义文件上传控件
                if (c.GetType() == typeof(FileField))
                {
                    if (pi.PropertyType == typeof(byte[]))
                    {
                        ((FileField)c).ValueData = (byte[])v;
                    }
                    else
                    {
                        ((FileField)c).Value = v.ToString();
                    }
                    continue;
                }
            }
        }

        public void GetEntityByControls<T>(ref T e, string controlPrefix, IList<Control> controls)
        {
            Control c;
            Type t = typeof(T);
            string v;
            foreach (string s in this.treeListComboBoxList)
            {
                c = controls.SingleOrDefault(a => a.ID == s);
                if (c == null) continue;
                // 自定义下拉控件
                if (c.GetType() == typeof(TreeListComboBox))
                {
                    SetEntityValue(typeof(T).GetProperty(s.Substring(controlPrefix.Length) + "ID"), ref e, ((TreeListComboBox)c).Value.ToGuid().ToString());
                    SetEntityValue(typeof(T).GetProperty(s.Substring(controlPrefix.Length) + "Name"), ref e, ((TreeListComboBox)c).Text);
                    continue;
                }
                // 自定义下拉控件
                if (c.GetType() == typeof(JqCombo))
                {
                    SetEntityValue(typeof(T).GetProperty(s.Substring(controlPrefix.Length) + "ID"), ref e, ((JqCombo)c).Value.ToGuid().ToString());
                    SetEntityValue(typeof(T).GetProperty(s.Substring(controlPrefix.Length) + "Name"), ref e, ((JqCombo)c).Text);
                    continue;
                }
                // 普通下拉控件
                if (c.GetType() == typeof(DropDownList))
                {
                    SetEntityValue(typeof(T).GetProperty(s.Substring(controlPrefix.Length) + "ID"), ref e, ((DropDownList)c).SelectedValue.ToGuid().ToString());
                    SetEntityValue(typeof(T).GetProperty(s.Substring(controlPrefix.Length) + "Name"), ref e, ((DropDownList)c).SelectedItem.Text);
                    continue;
                }
            }
            foreach (string s in this.cnRegionComboBoxList)
            {
                c = controls.SingleOrDefault(a => a.ID == s);
                if (c == null) continue;
                // 中国省市区控件
                if (c.GetType() == typeof(CNRegionComboBox))
                {
                    foreach (string cnregion in new string[] { "Province", "City", "Area" })
                    {
                        switch (cnregion)
                        {
                            case "Province":
                                SetEntityValue(typeof(T).GetProperty(cnregion), ref e, ((CNRegionComboBox)c).ProvinceValue);
                                break;
                            case "City":
                                SetEntityValue(typeof(T).GetProperty(cnregion), ref e, ((CNRegionComboBox)c).CityValue);
                                break;
                            case "Area":
                                SetEntityValue(typeof(T).GetProperty(cnregion), ref e, ((CNRegionComboBox)c).AreaValue);
                                break;
                        }
                    }
                    continue;
                }
            }
            foreach (PropertyInfo pi in t.GetProperties())
            {
                c = controls.SingleOrDefault(a => a.ID == controlPrefix + pi.Name);
                if (c == null) continue;

                // TextBox
                if (c.GetType() == typeof(TextBox))
                {
                    v = ((TextBox)c).Text;
                    if (v.Length == 0) continue;
                    SetEntityValue(pi, ref e, v);
                    continue;
                }
                // RadioButtonList
                if (c.GetType() == typeof(RadioButtonList))
                {
                    if (((RadioButtonList)c).SelectedIndex == -1) continue;
                    if (pi.PropertyType == typeof(short?) || pi.PropertyType == typeof(short))
                    {
                        pi.SetValue(e, ((RadioButtonList)c).Text.ToShort(), null);
                        continue;
                    }
                    if (pi.PropertyType == typeof(int?) || pi.PropertyType == typeof(int))
                    {
                        pi.SetValue(e, ((RadioButtonList)c).Text.ToInt(), null);
                        continue;
                    }
                    if (pi.PropertyType == typeof(bool?) || pi.PropertyType == typeof(bool))
                    {
                        pi.SetValue(e, ((RadioButtonList)c).Text.ToBoolean(), null);
                        continue;
                    }
                    pi.SetValue(e, ((RadioButtonList)c).SelectedValue, null);
                    continue;
                }
                // DropDownList
                if (c.GetType() == typeof(DropDownList))
                {
                    pi.SetValue(e, ((DropDownList)c).SelectedValue, null);
                    continue;
                }
                // CheckBox
                if (c.GetType() == typeof(CheckBox))
                {
                    pi.SetValue(e, ((CheckBox)c).Checked, null);
                    continue;
                }
                // Label
                if (c.GetType() == typeof(Label))
                {
                    v = ((Label)c).Text;
                    if (v.Length == 0) continue;
                    SetEntityValue(pi, ref e, v);
                    continue;
                }
                // HiddenField
                if (c.GetType() == typeof(HiddenField))
                {
                    v = ((HiddenField)c).Value;
                    if (v.Length == 0) continue;
                    SetEntityValue(pi, ref e, v);
                    continue;
                }
                if (c.GetType() == typeof(FileField))
                {
                    if (pi.PropertyType == typeof(byte[]))
                    {
                        pi.SetValue(e, ((FileField)c).GetValueData(), null);
                    }
                    else
                    {
                        SetEntityValue(pi, ref e, ((FileField)c).GetValue());
                    }
                    continue;
                }
            }
        }

        /// <summary>
        /// 设置实体对象的值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="pi"></param>
        /// <param name="e"></param>
        /// <param name="value"></param>
        private void SetEntityValue<T>(PropertyInfo pi, ref T e, string value)
        {
            if (pi == null || value.Length == 0) return;
            if (pi.PropertyType == typeof(string))
            {
                pi.SetValue(e, value, null);
                return;
            }
            if (pi.PropertyType == typeof(Guid?) || pi.PropertyType == typeof(Guid))
            {
                pi.SetValue(e, value.ToGuid(), null);
                return;
            }
            if (pi.PropertyType == typeof(int?) || pi.PropertyType == typeof(int))
            {
                pi.SetValue(e, value.ToInt(), null);
                return;
            }
            if (pi.PropertyType == typeof(short?) || pi.PropertyType == typeof(short))
            {
                pi.SetValue(e, value.ToShort(), null);
                return;
            }
            if (pi.PropertyType == typeof(DateTime?) || pi.PropertyType == typeof(DateTime))
            {
                pi.SetValue(e, value.ToDateTime(), null);
                return;
            }
            if (pi.PropertyType == typeof(decimal?) || pi.PropertyType == typeof(decimal))
            {
                pi.SetValue(e, value.ToDecimal(), null);
                return;
            }
            if (pi.PropertyType == typeof(double?) || pi.PropertyType == typeof(double))
            {
                pi.SetValue(e, value.ToDouble(), null);
                return;
            }
            pi.SetValue(e, value, null);
        }

        /// <summary>
        /// 获取实体对象值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="e"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        private object GetEntityValue<T>(ref T e, string name)
        {
            PropertyInfo pi = typeof(T).GetProperty(name);
            if (pi == null) return null;
            return pi.GetValue(e, null);
        }

        /// <summary>
        /// 获取表单的字典数据
        /// </summary>
        /// <param name="controlPrefix"></param>
        /// <param name="contentPlaceHolder"></param>
        /// <param name="filterControlIDs"></param>
        /// <returns></returns>
        public Dictionary<string, string> GetDictionaryByControls(string controlPrefix, IList<Control> controls, params string[] filterControlIDs)
        {
            Dictionary<string, string> dict = new Dictionary<string, string>();
            string id = string.Empty;
            foreach (Control c in controls)
            {
                if (string.IsNullOrEmpty(c.ID) || !c.ID.Contains(controlPrefix)) continue;
                id = c.ID.Substring(controlPrefix.Length);
                if (c.GetType() == typeof(TextBox))
                {
                    dict.Add(id, ((TextBox)c).Text);
                    continue;
                }
                if (c.GetType() == typeof(RadioButtonList))
                {
                    dict.Add(id, ((RadioButtonList)c).SelectedValue);
                    continue;
                }
                if (c.GetType() == typeof(HiddenField))
                {
                    dict.Add(id, ((HiddenField)c).Value);
                    continue;
                }
                if (c.GetType() == typeof(CheckBox))
                {
                    dict.Add(id, ((CheckBox)c).Checked.ToString());
                    continue;
                }
                if (c.GetType() == typeof(Label))
                {
                    dict.Add(id, ((Label)c).Text);
                    continue;
                }
                if (c.GetType() == typeof(FileField))
                {
                    dict.Add(id, ((FileField)c).GetValue());
                    continue;
                }
                if (c.GetType() == typeof(TreeListComboBox))
                {
                    dict.Add("{0}ID".Fmt(id), ((TreeListComboBox)c).Value);
                    dict.Add("{0}Name".Fmt(id), ((TreeListComboBox)c).Value);
                    continue;
                }
                if (c.GetType() == typeof(JqCombo))
                {
                    dict.Add("{0}ID".Fmt(id), ((JqCombo)c).Value);
                    dict.Add("{0}Name".Fmt(id), ((JqCombo)c).Value);
                    continue;
                }
                if (c.GetType() == typeof(CNRegionComboBox))
                {
                    dict.Add("Province", ((CNRegionComboBox)c).ProvinceValue);
                    dict.Add("City", ((CNRegionComboBox)c).CityValue);
                    dict.Add("Area", ((CNRegionComboBox)c).AreaValue);
                    continue;
                }
            }
            return dict;
        }

        public void BindFormByDictionary(string prefix, Page page, Dictionary<string, string> dict)
        {
            Control c;
            foreach (string k in dict.Keys)
            {
                c = page.FindControl(prefix + k);
                if (c == null) continue;

                if (c.GetType() == typeof(TextBox))
                {
                    ((TextBox)c).Text = dict[k];
                    continue;
                }
                if (c.GetType() == typeof(Label))
                {
                    ((Label)c).Text = dict[k];
                    continue;
                }
                if (c.GetType() == typeof(HiddenField))
                {
                    ((HiddenField)c).Value = dict[k];
                    continue;
                }
                if (c.GetType() == typeof(RadioButtonList))
                {
                    ((RadioButtonList)c).SelectedValue = dict[k];
                    continue;
                }
                if (c.GetType() == typeof(CheckBox))
                {
                    ((CheckBox)c).Checked = dict[k].ToBoolean();
                    continue;
                }
                // 自定义文件上传控件
                if (c.GetType() == typeof(FileField))
                {
                    ((FileField)c).Value = dict[k];
                    continue;
                }
            }
        }

        /// <summary>
        /// 从表单获取实体数据
        /// <para>2012-9-21</para>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="e"></param>
        /// <param name="prefix"></param>
        public void GetEntityByForm<T>(ref T e,string prefix="tb")
        {
            string s;
            foreach (PropertyInfo pi in typeof(T).GetProperties())
            {
                s = prefix.Length > 0 ? "{0}{1}".Fmt(prefix, pi.Name) : pi.Name;
                if (_Request.HasFormVar(s)) SetEntityValue<T>(pi, ref e, _Request.FormString(s));
            }
        }
    }
}
